grammar antlr;

@header {}
@lexer::header {}
@members {}

antlr		: line+ EOF ;
line		: label? instruction? NL ;
label		: NAMED_LABEL | LOCAL_LABEL | ADDRESS_LABEL ;
instruction	: binary | unary | expression ;
binary		: x binop C? y FLAG? register WRITE? ( register | LOAD ) ;
x		: ZERO | A ;
binop		: LHS | AND | OR | PLUS ;
y		: A | ASH | B | NOTB ;
unary		: UNOP CONDITIONAL? register expression;
register	: NAMED_REGISTER | (INDIR_REG_START expression INDIR_REG_STOP) ;
expression	: term ((PLUS  | MINUS) term)* ;
term		: factor ((MULT | DIV) factor)* ;
factor		: NUMBER | ID | CURSOR | (PAREN_START expression PAREN_STOP) ;
 
fragment DEC	: '1'..'9' '0'..'9'* ;
fragment HEX	: '0x' ('0'..'9' | 'a'..'f' | 'A'..'F')+ ;

NL		: ('#' ~('\n'|'\r')*)? '\r'? '\n' ;
WS	 	: (' '|'\t')+ {skip();} ;
NUMBER		: '-'? (DEC | HEX) ;

ID		: ('a'..'z'|'_') ('a'..'z'|'0'..'9'|'_')* ;
NAMED_LABEL	: ID ':' ;
LOCAL_LABEL	: '.' DEC ':' ;
ADDRESS_LABEL	: HEX ':' ;

PLUS		: '+' ;
MINUS		: '-' ;
MULT		: '*' ;
DIV		: '/' ;
PAREN_START	: '(' ;
PAREN_STOP	: ')' ;
CURSOR		: '$' ;

LOAD		: '@' ;
NAMED_REGISTER	: ('R' '0'..'7') | 'PC' | 'UPC' ;
INDIR_REG_START	: 'R[' ;
INDIR_REG_STOP	: ']' ;

UNOP		: 'SET' | 'INC' | 'DEC' ;
CONDITIONAL	: '?' ;

ZERO		: '0' ;
A		: 'A' ;
ASH		: 'A>' ;
B		: 'B' ;
NOTB		: '!B' ;
LHS		: '<' ;
AND		: '&' ;
OR		: '|' ;
C		: '.' ;
FLAG		: '.' ('F' | '0' | 'C' | '!C') ;
WRITE		: '!' ;

